#pragma once

#include "../RHIResource.h"
#include "RHISemaphore.h"
#include "RHIFence.h"

class RHICommandBuffer : public RHIResource
{
	struct BuilderDetails {

		VkCommandBufferAllocateInfo commandBufferAllocateInfo;

		VkQueueFlagBits queueFlag;

		VkCommandBufferUsageFlagBits commandBufferUsage;

		BuilderDetails();
	};

public:

	class Builder : public BuilderBase<BuilderDetails> {
		friend struct BuilderDetails;
	public:
		Builder() noexcept;
		Builder(Builder const& rhs) noexcept;
		Builder(Builder&& rhs) noexcept;
		~Builder() noexcept;
		Builder& operator=(Builder const& rhs) noexcept;
		Builder& operator=(Builder&& rhs) noexcept;

		Builder& SetQueue(VkQueueFlagBits queueFlag) noexcept;
		Builder& SetLevel(VkCommandBufferLevel level) noexcept;
		Builder& SetCount(uint32 count) noexcept;
		Builder& SetCommandBufferUsage(VkCommandBufferUsageFlagBits commandBufferUsage) noexcept;

		RefCountPtr<RHICommandBuffer> Build();
		RefCountPtr<RHICommandBuffer> Build(RenderProcess* process, const std::string& name);

	private:

		friend class RHICommandBuffer;
	};

	RHICommandBuffer(BuilderDetails& builderDetails);

	virtual void ReleaseResource() override;

	virtual ~RHICommandBuffer();

	VkCommandBuffer GetCommandBuffer(uint32 index = UINT32_MAX) const;

	VkQueueFlagBits GetQueueFlag() const;

	VkCommandBuffer BeginCommandBuffer(uint32 index = UINT32_MAX) const;

	void FlushCommandBuffer(VkCommandBuffer commandBuffer, std::vector<RefCountPtr<RHISemaphore>> waitSemaphores = {}, std::vector<RefCountPtr<RHISemaphore>> signalSemaphores = {}, RefCountPtr<RHIFence> fence = RefCountPtr<RHIFence>()) const;

protected:

	VkCommandBufferAllocateInfo mCommandBufferAllocateInfo;

	VkQueueFlagBits mQueueFlag;

	VkCommandBufferBeginInfo mCommandBufferBeginInfo;

	std::vector<VkCommandBuffer> mCommandBuffers;
};